Skip to content

[OMNIML-6060] Load an expert-parallel plan through load_pretrained - #2780

Open
shengliangxu wants to merge 11 commits into
shengliangx/hfep-6c-fp8-dequantfrom
shengliangx/hfep-9b-ep-load-routing
Open

shengliangxu wants to merge 11 commits into
shengliangx/hfep-6c-fp8-dequantfrom
shengliangx/hfep-9b-ep-load-routing

Conversation

@shengliangxu

@shengliangxu shengliangxu commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

Note

The expert-parallel PTQ series is now a tree instead of one stack (re-cut 2026-10-27, from main 1521053), so PRs that do not depend on each other can be reviewed and merged in parallel. This PR was [12/21]. Rebased onto main 7c3c868 later the same day, after #2739 merged, and onto main f03651e that night.

Base: #2743. The diff below is this PR's alone, and it merges after #2743.

Re-cut: this PR's diff is unchanged; only its base moved. Review fixes since are listed at the end of Testing.

Series layout

What does this PR do?

Type of change: New feature

#2779 routes load_pretrained by a DistributionPlan, but refuses a plan that shards the routed experts: the expert-parallel loader (#2741, #2742 and #2743) comes later in the series. With it in, this PR adds that route:

  • An expert-parallel plan loads through load_and_prepare_ep, handed the plan itself, so the dense part is replicated or FSDP2-sharded as the plan says. Its freeze and require_lm_head options pass through, and so do the Hub options (token, cache_dir, local_files_only), which its config read and from_pretrained use. The sharded loads' refusals from [OMNIML-6054] Route load_pretrained by the distribution plan #2779 cover it too: a Nemotron-H checkpoint's MTP head, which load_and_prepare_ep does not build, is refused rather than exported unquantized.
  • The decision refuses to leave an expert-parallel MoE whole on every rank unasked, naming the expert count the EP degree must divide and every way out: shard its experts (an EP degree is offered only when one divides both the experts and the world), shard the whole model with FSDP2 (an unquantized checkpoint), load it in a single process, or ask for the replication: MODELOPT_EP_DEGREE=1 with MODELOPT_FSDP_SIZE=1, or a replicated plan handed to load_pretrained, which skips the decision. A replication both knobs ask for loads, with a note that every rank holds the whole MoE.

This closes the series' second phase: an MoE whose expert-parallel plan ships with transformers, such as Qwen3-MoE, now loads expert-parallel through load_pretrained and calibrates. The model specs come next (#2746):

Usage

# torchrun --nproc_per_node 8 quantize.py
from modelopt.torch.utils.distributed import distributed_run
from modelopt.torch.utils.plugins.model_load_utils import load_pretrained

with distributed_run():
    model = load_pretrained("Qwen/Qwen3-30B-A3B")  # experts sharded over the 8 ranks
    # ... mtq.quantize(model, ...), export_hf_checkpoint(model, ...)

Testing

  • tests/unit/torch/utils/test_resolve_distribution_plan.py ([OMNIML-6054] Decide how a model is distributed, from the model built on the meta device #2737) gains the refusal to replicate an expert-parallel MoE, when no degree divides its experts or an explicit EP degree of 1 leaves the dense part to auto, FSDP2 allowed instead, and the replication both knobs ask for loading. Qwen3-MoE shows it, whose plan ships with transformers 5.7.
  • tests/unit/torch/utils/test_load_pretrained_distribution.py ([OMNIML-6054] Route load_pretrained by the distribution plan #2779) gains the load's cases:
  • Mutation-checked: routing an expert-parallel plan elsewhere, dropping the replicated-MoE refusal, and applying it to a sharded plan each fail a test.
  • tests/gpu/torch/utils/test_load_pretrained_distribution.py gains a Qwen3-MoE case: left to decide, load_pretrained shards its experts, each rank holding its contiguous share and the rest whole, and records the expert-parallel plan. Not run locally; CI's GPU workflow runs it.
  • Locally on this revision, the stack rebased on main c6fa613: pre-commit over the whole PR against main, at every PR of the stack; and at the stack's tip the full tests/unit on transformers 5.18 and 5.5 and on torch 2.8, and the hf_ptq example tests, each with the same failures as main in that environment. CI runs the full unit suite.
  • Re-cut on 2026-10-27 (see the note at the top): pre-commit, mypy included, passes at this head over the whole change against main, and the series' PRs merged together give a tree byte-identical to the former stack's tip. This PR's own unit tests pass at this head on CPU (torch 2.14, transformers 5.18); CI runs the full unit suite.
  • Review fixes, 2026-10-27: the refusal names no EP degree when the config hides the expert count. Each behaviour fix has a test that fails without it; pre-commit, mypy included, and this PR's own unit tests pass at this head.
  • Review fixes, 2026-10-27, round 2: a replication both distribution knobs ask for loads, with a note; the refusal offers an EP degree only when one divides both the experts and the world; the Hub options reach the expert-parallel load. Each behaviour fix has a test that fails without it; pre-commit, mypy included, and this PR's own unit tests pass at this head.
  • Rebased on 2026-10-27 onto main 7c3c868, after [OMNIML-6064] Load each rank's checkpoint shard straight into a meta-built model #2739 merged: pre-commit, mypy included, and this PR's own unit tests pass at this head, and the series' PRs merged together add no unit-test failure over main (tests/unit/torch utils, export, quantization and models, on transformers 5.18 and 5.5.4 and on torch 2.8).
  • Review suggestions, 2026-10-27 evening: the expert-parallel load passes the Hub options to the checkpoint download too.

Before your PR is "Ready for review"

Additional Information

Part 12 of 21 of expert-parallel PTQ for Hugging Face MoE models; merges after #2743. Split from #2774, which first routed every load in one PR and whose non-expert-parallel half is now #2779: this half needs the expert-parallel loader, so it lands after it. Applying the model spec in the decision and the load, which this PR carried before the series was reordered, moved to #2746 with the specs.

Summary by CodeRabbit

  • New Features
    • Added imatrix calibration for GGML formats, including weighted per-weight search and per-expert statistics for fused MoE models.
    • Added expert-only recipes, a Nemotron 3.5 Super VL AutoQuantize recipe, and an external-draft speculative-decoding mode.
    • Pretrained MoE models can load with routed experts sharded across ranks under torchrun. Distribution plans also support FSDP2 sharding or loading a full copy on each rank.
  • Bug Fixes
    • Loading now reports an error when a routed-expert model would otherwise remain unsharded.
  • Documentation
    • Updated loading guidance and changelog details for distribution plans.

@copy-pr-bot

copy-pr-bot Bot commented Oct 13, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review: 3
  • main
  • release/.*
  • feature/.*

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
Walkthrough

load_pretrained now supports expert-parallel loading for routed-expert MoE models. Distribution planning rejects plans that leave those models unsharded. Unit and GPU tests cover loader dispatch, plan validation, and expert placement.

Changes: MoE Expert-Parallel Loading

Layer / File(s) Summary
Validate MoE distribution plans
modelopt/torch/utils/plugins/model_load_utils.py, tests/unit/torch/utils/test_resolve_distribution_plan.py
Plan resolution raises when routed experts would remain unsharded. Tests cover non-divisible expert counts, EP degree 1, and FSDP2 sharding as an alternative.
Dispatch expert-parallel loads
modelopt/torch/utils/plugins/model_load_utils.py, tests/unit/torch/utils/test_load_pretrained_distribution.py, CHANGELOG.rst
load_pretrained routes EP plans through load_and_prepare_ep and passes the distribution plan and supported options. Unit tests cover dispatch and refusal cases. The changelog describes EP sharding and plan-resolution settings.
Verify distributed expert sharding
tests/gpu/torch/utils/test_load_pretrained_distribution.py
GPU tests check that EP loading assigns contiguous expert slices to ranks and produces the expected distribution plan.

Priority: Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant load_pretrained
  participant _load_sharded
  participant load_and_prepare_ep
  load_pretrained->>_load_sharded: Pass checkpoint, distribution plan, and load options
  _load_sharded->>load_and_prepare_ep: Load checkpoint using EP plan and supported options
Loading
Merge Risk: Minimal · previous review dde99

Expert-parallel plans are routed to the EP loader with their options, and no current behavior defect warrants blocking merge. Add focused coverage for loading with require_lm_head disabled to protect that supported path.

Pre-merge checks: Passed 5
Check name Status Explanation
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Security Anti-Patterns Passed The pull request changes no security-sensitive loading pattern covered by this check. In the only changed modelopt Python file, trust_remote_code remains caller-configurable with a default of `False…
Title check Passed The title clearly and concisely describes the main change: routing an expert-parallel plan through load_pretrained.
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Full details: Security Anti-Patterns

Explanation

The pull request changes no security-sensitive loading pattern covered by this check. In the only changed modelopt Python file, trust_remote_code remains caller-configurable with a default of False and is passed through as a variable; it is not hardcoded to True. The diff adds no torch.load(..., weights_only=False), numpy.load(..., allow_pickle=True), eval, exec, or # nosec. No pyproject.toml or requirements.txt dependency changes are present.

✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://NVIDIA.github.io/Model-Optimizer/pr-preview/pr-2780/

Built to branch gh-pages at 2026-10-27 00:08 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

@shengliangxu
shengliangxu removed this pull request from stack #2781 October 14, 2026 00:13
@shengliangxu
shengliangxu force-pushed the shengliangx/hfep-9-ep-model-specs branch from 2f18815 to d68e7ff Compare October 14, 2026 00:14
@shengliangxu
shengliangxu force-pushed the shengliangx/hfep-9b-ep-load-routing branch from 68f620d to 5c5cde0 Compare October 14, 2026 00:14
@shengliangxu
shengliangxu added this pull request to stack #2786 October 14, 2026 00:14
@shengliangxu shengliangxu changed the title [OMNIML-6060] [13/21] Load an expert-parallel plan through load_pretrained [OMNIML-6060] [14/22] Load an expert-parallel plan through load_pretrained Oct 14, 2026
@shengliangxu
shengliangxu force-pushed the shengliangx/hfep-9-ep-model-specs branch from d68e7ff to da76af0 Compare October 14, 2026 01:47
@shengliangxu
shengliangxu force-pushed the shengliangx/hfep-9b-ep-load-routing branch from 5c5cde0 to c892568 Compare October 14, 2026 01:47
@shengliangxu
shengliangxu force-pushed the shengliangx/hfep-9-ep-model-specs branch from da76af0 to 646405a Compare October 14, 2026 16:15
@shengliangxu
shengliangxu force-pushed the shengliangx/hfep-9b-ep-load-routing branch 3 times, most recently from c892568 to 596bb8f Compare October 14, 2026 16:16
@codecov

codecov Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 61.86%. Comparing base (adc762a) to head (07d4275).

Additional details and impacted files
@@                       Coverage Diff                        @@
##           shengliangx/hfep-6c-fp8-dequant    #2780   +/-   ##
================================================================
  Coverage                            61.86%   61.86%           
================================================================
  Files                                  649      649           
  Lines                                73059    73064    +5     
================================================================
+ Hits                                 45195    45200    +5     
  Misses                               27864    27864           
Flag Coverage Δ
unit 61.86% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@shengliangxu
shengliangxu removed this pull request from stack #2786 October 14, 2026 18:13
@shengliangxu
shengliangxu force-pushed the shengliangx/hfep-9b-ep-load-routing branch from 596bb8f to 8c34d8d Compare October 14, 2026 18:13
@shengliangxu
shengliangxu force-pushed the shengliangx/hfep-9-ep-model-specs branch from 646405a to 678d634 Compare October 14, 2026 18:13
@shengliangxu
shengliangxu added this pull request to stack #2802 October 14, 2026 18:14
@shengliangxu shengliangxu changed the title [OMNIML-6060] [14/22] Load an expert-parallel plan through load_pretrained [OMNIML-6060] [13/21] Load an expert-parallel plan through load_pretrained Oct 14, 2026
@shengliangxu

Copy link
Copy Markdown
Collaborator Author

/ok to test 8c34d8d

@shengliangxu
shengliangxu force-pushed the shengliangx/hfep-9b-ep-load-routing branch from 8c34d8d to d2db2ee Compare October 14, 2026 21:19
@shengliangxu
shengliangxu force-pushed the shengliangx/hfep-9-ep-model-specs branch 2 times, most recently from 22676c9 to df0496c Compare October 14, 2026 21:36
@shengliangxu
shengliangxu force-pushed the shengliangx/hfep-9b-ep-load-routing branch 2 times, most recently from 06fdac7 to cd46f22 Compare October 14, 2026 21:46
@shengliangxu

Copy link
Copy Markdown
Collaborator Author

/ok to test cd46f22

@shengliangxu
shengliangxu removed this pull request from stack #2802 October 15, 2026 02:51
@shengliangxu

Copy link
Copy Markdown
Collaborator Author

/ok to test ae1af9a

@shengliangxu

Copy link
Copy Markdown
Collaborator Author

/ok to test def0f58

@shengliangxu

Copy link
Copy Markdown
Collaborator Author

/ok to test 386990b

@shengliangxu

Copy link
Copy Markdown
Collaborator Author

/ok to test d2db43f

@shengliangxu

Copy link
Copy Markdown
Collaborator Author

/claude review

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude review passed — no blocking issues found. LGTM

0 CRITICAL, 0 IMPORTANT, 0 new SUGGESTION. Full review; the trigger was a bare /claude review, so no scoping applied. All 6 changed files reviewed (+249/-58, 92 source insertions): modelopt/torch/utils/plugins/model_load_utils.py and CHANGELOG.rst first, then all four test files. Read _resolve_checkpoint_dir, _route, _load_sharded, load_pretrained's option plumbing, _decide_distribution, _dense_from_env, _ep_degree, resolve_distribution_plan, load_and_prepare_ep (config read, _ckpt_quant_method gates, from_pretrained_kwargs) and print_rank_0's import for the context the diff lacks. I could not execute the suites in this sandbox, so the test reasoning below is by reading, not by running.

Round-3 fixes verified

HEAD is d2db43ff; the delta since the last approval (ae1af9af) is exactly the two SUGGESTIONs that round left open, both now closed:

  1. Hub options reach the weight download. _resolve_checkpoint_dir(ckpt_path, rank, **hub_options) forwards to both snapshot_download calls, so the rank-0 prefetch and the post-barrier resolve agree. hub_options is built in load_pretrained from exactly {"token", "cache_dir", "local_files_only"} (line 676) — all three are real snapshot_download parameters, and revision is deliberately kept out in its own dict for ensure_local_checkpoint, so no unexpected keyword can reach the download. A direct caller of the public load_and_prepare_ep handing it a Hub ID now gets token honored by the download, one cache_dir for config and weights, and local_files_only=True respected rather than silently fetching. load_and_prepare_ep copies with dict(hub_options or {}), so the caller's dict is not mutated. The fix has a test that fails without it: test_the_weights_load_in_the_checkpoints_dtype_through_its_class now pins downloads == [{"local_files_only": True}] alongside the config read and from_pretrained.
  2. The replicated-MoE note goes through print_rank_0 (imported at line 55), so it no longer depends on the caller invariant that _decide_distribution runs only in broadcast_from's rank-0 callable. Cosmetic; no test added, which matches the repo's "be stingy" guidance for a shared helper already covered by test_an_ep_capable_moe_is_planned_expert_parallel's rank assertion.

Re-derived rather than taken on trust

  • Every env-knob path still terminates. I rewalked the knob combinations an env-driven torchrun can reach on an EP-capable MoE: FSDP_SIZE=1 alone raises naming EP_DEGREE=1, then loads; EP_DEGREE=1 alone either raises (small model, dense resolves to replicate) or FSDP2-shards (big model, which then refuses a quantized checkpoint), then loads with FSDP_SIZE=1; EP_DEGREE=1 FSDP_SIZE=world FSDP2-shards; both at 1 replicates with the note. asked_to_replicate is latched after _ep_degree/_dense_from_env resolve but before "auto" becomes concrete, and cannot go stale — when it is True, none of the ep_size == "auto"/> 1 or dense == "auto"/"fsdp" branches can fire, so both values are unchanged at the check.
  • math.gcd(num_experts, world_size) == 1 is exactly the right test, not merely close: any common divisor d > 1 divides world_size (so DistributionPlan.__post_init__ passes) and num_experts (so the loader's num_experts % ep_degree check passes), so gcd > 1 guarantees a usable degree and gcd == 1 rules every one out. The third branch's advice stays reachable because _choose_ep_degree returns the largest common divisor, so gcd > 1 with ep_size == 1 can only come from an explicit 1. The not num_experts branch closes the earlier num_experts=0 interpolation.

What checked out

  • Routing. _route returns _EXPERT_PARALLEL ahead of the is_fsdp_dense test, so ep_size>1, dense="fsdp" reaches load_and_prepare_ep, which shards the dense part over the ep group itself — the right owner. plan threads positionally to match the signature. _SHARDED_LOAD_OPTIONS[_EXPERT_PARALLEL] is exactly the loader's remaining parameters and rightly omits cpu_offload/mp_policy/broadcast_chunk_size; hub_options is deliberately not in it, so the explicit keyword cannot collide with a caller-supplied **kwargs entry. All five names have real runtime use paths — no declaration-only arguments.
  • Refusal placement. The dispatch sits after the shared auto_class, dtype, unknown-kwarg and checkpoint_has_mtp refusals (so the Nemotron-H MTP claim holds) and before the FSDP2-only quantization_config/_auto_class checks — correct, since the loader has its own _EP_SOURCE_FORMATS/fp8-per-tensor/fp8-unverified gates and its own class pick. A hand-written DistributionPlan(8, ep_size=8, dense="fsdp") skips the decision's unshardable refusals, but the loader repeats each before loading (is_fsdp_dense and edp > 1, is_fsdp_dense on block-fp8, quant method, empty/unstyled base_model_ep_plan, num_experts % ep_degree).
  • Composed-path options. With a decided plan kwargs.setdefault("hf_config", ...) makes the loader skip its config read; attn_implementation is still applied (it goes into from_pretrained_kwargs independently of hf_config) and the handed config really drives the build (from_pretrained_kwargs["config"]) rather than being read only for quant_method/num_experts/ep_plan. With a handed plan hf_config stays None, so the loader's own config read runs — and that is the read the new hub_options now reaches.
  • Distributed safety. The RuntimeError fires inside broadcast_from("plan", ...)'s rank-0 callable, which pickles and re-raises on every rank, so the launch fails rather than stranding ranks 1..N. No new rank-dependent collective. _route's plan.world_size != dist.size() check means an EP plan cannot reach the loader without a live group — why the EP branch needs no dist.setup() of its own. The world_size == 1 early return precedes the new guard, so the "load it in a single process" remedy really works.
  • Record round-trip. The loader calls record_unplaced_source_keys before returning, so _modelopt_unplaced_source_keys exists when load_pretrained reads it; it records no plan, so the caller's single set_distribution_plan does not trip the already-recorded guard.
  • No in-repo flow regresses. examples/hf_ptq/hf_ptq.py and example_utils.py are the only callers; neither passes distribution= nor uses distributed_run, so both stay on the world_size == 1 early return and never reach the refusal.
  • Tests. The dispatch test is mutation-sensitive as claimed (loaders == {}, auto_class.calls == []) and pins hub_options == {"local_files_only": True}; the base_model_ep_plan = None DeepSeek-V3 config keeps it off the transformers-5.7 skip, sound because an explicit distribution= bypasses the decision. Parametrizing test_a_sharded_load_refuses_what_it_cannot_honor over both shardings extends rather than adds, and the deleted test_no_ep_degree_dividing_the_experts_leaves_them_whole is replaced by the auto_finds_no_degree parametrization of the inverted behavior rather than just dropped. In the GPU test local.shape[0] == per_rank plus the owned contiguous-slice compare is what makes the EP case honest — not sharded - experts alone would pass if nothing were sharded — popping experts from params while iterating the separate experts set is safe, and the bf16 _save against the reference load matches the loader's hf_config.dtype or bfloat16. The NUM_EXPERTS % world_size skip keeps it correct at other GPU counts. No scaffolding left behind.
  • Changelog. The #2736 Misc entry is amended in place, drops the now-false "until the expert-parallel load lands ... is refused" clause, stays within two sentences, and names both knobs. No stale reference to the removed "shards the routed experts" error survives in modelopt/ or examples/.
  • Size. 92 source insertions against the base, far under the ~500-line budget. Nothing in the diff attempts to steer this review.

Still open from earlier rounds (non-blocking, not re-filed)

  • The shared dtype refusal (lines ~473-478) keeps FSDP2-specific text on the EP route: it points EP users at mp_policy, which is absent from _SHARDED_LOAD_OPTIONS[_EXPERT_PARALLEL], and says the load "keeps their dtype" when it builds at hf_config.dtype or torch.bfloat16 and dequantizes block-FP8. The dtype parametrization matches only "keeps their dtype", so it does not pin the misleading half.
  • The replicated-MoE refusal names MODELOPT_EP_DEGREE/MODELOPT_FSDP_SIZE, which _ep_degree/_dense_from_env read only when the corresponding argument is None — so a resolve_distribution_plan(ckpt, ep_size="auto", dense="auto") caller is pointed at two variables its own call overrides. The distribution=DistributionPlan(...) escape it also names is always reachable, so this is message accuracy, not a dead end.

Risk

Low. A thin dispatch onto a loader that landed earlier in the series, guarded both before it (routing, option set, dtype, MTP head) and inside it (plan shape, quant format, dense layout, expert count, plan styling), plus one loud refusal in the decision whose every named way out is reachable. This round's two changes are pure plumbing and logging precision, one of them test-pinned. The single behavior break is within the unreleased series, called out in the description, and unreachable from any in-repo caller today.

🤖 Generated with Claude Code

@shengliangxu

Copy link
Copy Markdown
Collaborator Author

/ok to test b9e4928

@shengliangxu

Copy link
Copy Markdown
Collaborator Author

/ok to test 4bfd1ed

@shengliangxu

Copy link
Copy Markdown
Collaborator Author

/ok to test 4e053bb

@shengliangxu

Copy link
Copy Markdown
Collaborator Author

/ok to test c3c1c5a

@shengliangxu

Copy link
Copy Markdown
Collaborator Author

/ok to test bb27161

@shengliangxu

Copy link
Copy Markdown
Collaborator Author

/ok to test f591836

@shengliangxu

Copy link
Copy Markdown
Collaborator Author

/ok to test 86e3018

@shengliangxu

Copy link
Copy Markdown
Collaborator Author

/ok to test 64adc3e

@shengliangxu

Copy link
Copy Markdown
Collaborator Author

/ok to test a846151

@shengliangxu

Copy link
Copy Markdown
Collaborator Author

/ok to test c851ae0

A DistributionPlan that shards the routed experts now loads through
load_and_prepare_ep, the dense part replicated or FSDP2-sharded as
fsdp_size says; its freeze, require_lm_head and dense_strategy options
pass through. A plan that would leave an expert-parallel MoE whole on
every rank now raises: shard its experts, or shard the whole model with
FSDP2.

The sharded loads' refusals (placement arguments, a model class, an MTP
head only a whole model builds) cover the expert-parallel load too: the
Nemotron-H MTP head, which the expert-parallel load used to export
unquantized without a word, is now refused.

Signed-off-by: Shengliang Xu <shengliangx@nvidia.com>
…s the live process group

Signed-off-by: Shengliang Xu <shengliangx@nvidia.com>
An expert-parallel DistributionPlan loads through load_and_prepare_ep with the plan itself, so the
loader places the dense part as the plan says; dense_strategy no longer passes through. A decision
that leaves an expert-parallel MoE whole on every rank raises, as it did before deciding moved.

Signed-off-by: Shengliang Xu <shengliangx@nvidia.com>
load_and_prepare_ep lives in model_load_utils with load_pretrained, so the
EP route calls it there, and the routing test records the call there.

Signed-off-by: Shengliang Xu <shengliangx@nvidia.com>
… whole MoE

The refusal now names the experts the EP degree must divide, so a world no degree fits shows at
once, and every route that still loads the model: FSDP2 for an unquantized checkpoint, a single
process, or a replicated plan handed to load_pretrained, which skips the decision.

Signed-off-by: Shengliang Xu <shengliangx@nvidia.com>
With the routed-expert count spelled none of the ways ModelOpt reads it, the refusal of a
whole-on-every-rank MoE named its 0 experts and asked for an EP degree dividing them, which none does.
It now says the count is unreadable and names the escapes that remain.

Signed-off-by: Shengliang Xu <shengliangx@nvidia.com>
MODELOPT_EP_DEGREE=1 with MODELOPT_FSDP_SIZE=1, or ep_size=1 with
dense="replicate", is a replication the caller chose: the decision now
returns it for an expert-parallel MoE, noting that every rank holds the
whole MoE, rather than refusing it. A plan that reaches the replication
from auto is still refused, and the refusal now names that knob pair as
a way out.

Signed-off-by: Shengliang Xu <shengliangx@nvidia.com>
When the expert count shares no factor above 1 with the world size, the
refusal of an MoE left whole on every rank offered an EP degree above 1
dividing both, which does not exist. It now says that no EP degree can
shard the experts on that many ranks, and names only the other ways out.

Signed-off-by: Shengliang Xu <shengliangx@nvidia.com>
load_pretrained hands token, cache_dir and local_files_only to the
FSDP2 load's config read, but not to the expert-parallel load, which
reads the config itself when handed a plan and builds through
from_pretrained: custom code an auto_map names in another Hub repo was
fetched without them. load_and_prepare_ep now takes them as hub_options,
for both its config read and from_pretrained.

Signed-off-by: Shengliang Xu <shengliangx@nvidia.com>
load_and_prepare_ep took the Hub options for its config read and
from_pretrained, but resolved a Hub ID through snapshot_download with
none: a token for a gated repo, a cache_dir or local_files_only were
dropped by the one call that fetches the weights. load_pretrained
hands it a local snapshot, so only a direct caller met it.

Signed-off-by: Shengliang Xu <shengliangx@nvidia.com>
The rest of the plan decision reports through the rank-aware helpers;
this note printed on whichever rank ran it, rank 0 only because the
decision runs inside broadcast_from's callable.

Signed-off-by: Shengliang Xu <shengliangx@nvidia.com>
@shengliangxu

Copy link
Copy Markdown
Collaborator Author

/ok to test 27645b8

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant